package com.lingjtx.common.thread.commom;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lingjtx.common.core.RedisOptions;
import com.lingjtx.common.thread.api.WebClientApi;
import com.lingjtx.common.thread.config.ObjectPoolTemplateConfig;
import com.lingjtx.common.thread.core.ThreadPoolManager;
import com.lingjtx.common.thread.mq.*;
import com.lingjtx.common.thread.pooling.ObjectFactory;
import com.lingjtx.common.thread.pooling.ObjectPoolTemplate;
import com.lingjtx.common.thread.pooling.RabbitStreamEnvironmentFactory;
import com.lingjtx.common.thread.pooling.RabbitTemplateFactory;
import com.rabbitmq.stream.Environment;
import jakarta.mail.Session;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.reactive.function.client.WebClient;

import java.net.http.HttpClient;
import java.util.List;

/**
 * 示例配置文件，没有自动装配的文件
 * 按需配置 Bean 对象
 */
@Configuration
public class ExampleConfig {

    // ========== 配置注入示例 ==========
    @Bean
    public ApiKeyFilter apiKeyFilter() {
        return new ApiKeyFilter();
    }

    @Bean
    public ApiSignatureFilter apiSignatureFilter(RedisOptions redis) {
        return new ApiSignatureFilter(redis);
    }

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(RestResponseConfig config) {
        return config.jacksonObjectMapper();
    }

    @Bean
    public NettyServerExceptionResolver resolver() {
        return new NettyServerExceptionResolver();
    }

    @Bean("mailObjectPoolTemplate")
    public ObjectPoolTemplate<Session> mailObjectPoolTemplate(ObjectPoolTemplateConfig config) {
        return config.mailObjectPoolTemplate();
    }

    @Bean("httpObjectPoolTemplate")
    public ObjectPoolTemplate<HttpClient> httpObjectPoolTemplate(ObjectPoolTemplateConfig config) {
        return config.httpObjectPoolTemplate();
    }

    // ===========  WebClientApi 使用时与 webClientObjectPoolTemplate 一起注入 ============
    @Bean("webClientObjectPoolTemplate")
    public ObjectPoolTemplate<WebClient> webClientObjectPoolTemplate(ObjectPoolTemplateConfig config) {
        return config.webClientObjectPoolTemplate();
    }

    @Bean
    public WebClientApi webClientApi(ObjectPoolTemplateConfig config) {
        return config.webClientApi();
    }

    // ======= rabbitObjectPoolTemplate 使用时，必须与 FastJsonAutoTypeMessageConverter 一起注入才能使用 ==============
    @Bean
    public FastJsonAutoTypeMessageConverter fastJsonAutoTypeMessageConverter() {
        List<String> whitelistPackages = List.of("com.lingjtx.common.core.model.mq");
        return new FastJsonAutoTypeMessageConverter(whitelistPackages);
    }

    @Bean("rabbitObjectPoolTemplate")
    public ObjectPoolTemplate<RabbitTemplate> rabbitObjectPoolTemplate(ObjectPoolTemplateConfig config,
                                                                       CachingConnectionFactory rabbitConnectionFactory,
                                                                       FastJsonAutoTypeMessageConverter converter) {
        ObjectFactory<RabbitTemplate> rabbitTemplateObjectFactory = new RabbitTemplateFactory(config.getThreadPoolManager(),
                rabbitConnectionFactory, converter);
        return config.buildTemplate("rabbit", rabbitTemplateObjectFactory);
    }

    @Bean
    public RabbitSenderTemplate rabbitSenderTemplate(@Qualifier("rabbitObjectPoolTemplate") ObjectPoolTemplate<RabbitTemplate> rabbitPool) {
        return new RabbitSenderTemplate(rabbitPool);
    }

    // ===== 若需要使用 rabbitmq stream 就按需配置 bean 示例，在 SpringBoot 项目中注入
    @Bean
    @ConfigurationProperties(prefix = "spring.rabbit.stream")
    public RabbitStreamConsumerProperties rabbitStreamConsumerProperties() {
        return new RabbitStreamConsumerProperties();
    }

    @Bean("environmentObjectPoolTemplate")
    public ObjectPoolTemplate<Environment> environmentObjectPoolTemplate(ObjectPoolTemplateConfig config,
                                                                         RabbitStreamConsumerProperties props) {
        ObjectFactory<Environment> environmentObjectFactory = new RabbitStreamEnvironmentFactory(config.getThreadPoolManager(), props);
        return config.buildTemplate("environment", environmentObjectFactory);
    }

    @Bean
    public RabbitStreamProducer rabbitStreamProducer(
            @Qualifier("environmentObjectPoolTemplate") ObjectPoolTemplate<Environment> environmentObjectPoolTemplate,
            FastJsonAutoTypeMessageConverter converter) {
        return new RabbitStreamProducer(environmentObjectPoolTemplate, converter);
    }

    @Bean
    public RabbitStreamConsumer rabbitStreamConsumer(
            @Qualifier("environmentObjectPoolTemplate") ObjectPoolTemplate<Environment> environmentObjectPoolTemplate,
            FastJsonAutoTypeMessageConverter converter,
            ThreadPoolManager threadPoolManager,
            RabbitStreamConsumerProperties properties) {
        return new RabbitStreamConsumer(environmentObjectPoolTemplate, converter, threadPoolManager, properties);
    }

    // ===== 若需要使用 meilisearch 就按需配置 bean 示例，在 SpringBoot 项目中注入

}
